package com.spzx.order.receiver;

import com.rabbitmq.client.Channel;
import com.spzx.common.rabbit.constants.MqConst;
import com.spzx.order.configure.DeadLetterMqConfig;
import com.spzx.order.configure.DelayedMqConfig;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.util.concurrent.TimeUnit;

@Slf4j
@Component
public class TestReceiver {

    @Autowired
    RedisTemplate redisTemplate;


    //@RabbitListener(queues = MqConst.QUEUE_TEST)
    @RabbitListener(bindings = {
        @QueueBinding(
                exchange =  @Exchange(name = MqConst.EXCHANGE_TEST,durable = "true"),
                value = @Queue(name = MqConst.QUEUE_TEST,durable = "true"),
                key = {
                        MqConst.ROUTING_TEST
                }
        )
    })
    public void receiver(String msg, Message message, Channel channel){
        log.info("消费者接收消息：{}",msg);
        log.info("消息属性：{}",message.getMessageProperties());
        //默认：消费端自动确认消息。
        //channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);
    }


    /**
     * 监听确认消息
     * @param message
     */
    @SneakyThrows
    @RabbitListener(bindings = @QueueBinding(
            exchange = @Exchange(value = MqConst.EXCHANGE_TEST, durable = "true"),
            value = @Queue(value = MqConst.QUEUE_CONFIRM, durable = "true"),
            key = MqConst.ROUTING_CONFIRM
    ))
    public void confirm(String content, Message message, Channel channel) /*throws Exception*/{
        log.info("接收确认消息：{}", content);

        // false 确认一个消息，true 批量确认
        // deliveryTag 是一个整数值，用于表示消息唯一性。类似ID
        channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
    }


    /**
     * 监听延迟消息
     * @param msg
     * @param message
     * @param channel
     */
    @SneakyThrows
    @RabbitListener(queues = {DeadLetterMqConfig.queue_dead_2})
    public void getDeadLetterMsg(String msg, Message message, Channel channel) {
        log.info("死信消费者：{}", msg);
        channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
    }

    /**
     * 监听重复消息处理：保证幂等性。
     * @param msg
     * @param message
     * @param channel
     */
    @SneakyThrows
    @RabbitListener(queues = DelayedMqConfig.queue_delay_1)
    public void getDelayMsgs(String msg, Message message, Channel channel) {

        String lockKey = "mq:"+msg;
        Boolean ifAbsent = redisTemplate.opsForValue().setIfAbsent(lockKey, "", 200, TimeUnit.SECONDS);
        if(!ifAbsent){
            log.info("设置分布式锁失败，处理重复消息,不需要进行业务逻辑处理，直接确认:{}",msg);
            channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
            return; //注意：注意：注意：
        }
        //设置分布式锁成功，就执行相关的业务逻辑处理
        log.info("设置分布式锁成功，就执行相关的业务逻辑处理:{}",msg);
        channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
    }



}
